/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.biz.service.impl;

import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import cn.hutool.core.convert.Convert;
import me.zhengjie.modules.biz.domain.*;
import me.zhengjie.modules.biz.domain.FumeHood;
import me.zhengjie.modules.biz.domain.FumeHoodLog;
import me.zhengjie.modules.biz.domain.Lab;
import me.zhengjie.modules.biz.repository.LabRepository;
import me.zhengjie.modules.biz.service.dto.CabinetDto;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.biz.repository.FumeHoodRepository;
import me.zhengjie.modules.biz.service.FumeHoodService;
import me.zhengjie.modules.biz.service.dto.FumeHoodDto;
import me.zhengjie.modules.biz.service.dto.FumeHoodQueryCriteria;
import me.zhengjie.modules.biz.service.mapstruct.FumeHoodMapper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;

import java.lang.System;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author Admin
* @date 2023-02-16
**/
@Service
@RequiredArgsConstructor
public class FumeHoodServiceImpl implements FumeHoodService {

    private final FumeHoodRepository fumeHoodRepository;
    private final FumeHoodMapper fumeHoodMapper;
    private final LabRepository labRepository;

    @Override
    public Map<String,Object> queryAll(FumeHoodQueryCriteria criteria, Pageable pageable){
        Page<FumeHood> page = fumeHoodRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        Page<FumeHoodDto> dto = page.map(fumeHoodMapper::toDto);
        List<FumeHoodDto> resultDto = dto.getContent();
        for (FumeHoodDto fumeHoodDto:resultDto) {
            if (fumeHoodDto.getLabId() != null) {
                Lab lab = labRepository.findById(fumeHoodDto.getLabId()).orElseGet(Lab::new);
                ValidationUtil.isNull( lab.getId(),"Lab","id",fumeHoodDto.getLabId());
                fumeHoodDto.setLabName(lab.getName());
            }
        }
        return PageUtil.toPage(dto);
    }

    @Override
    public List<FumeHoodDto> queryAll(FumeHoodQueryCriteria criteria){
        List<FumeHood> fumeHoodList = fumeHoodRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
        List<FumeHoodDto> fumeHoodDtoList = fumeHoodMapper.toDto(fumeHoodList);
        for (FumeHoodDto fumeHoodDto : fumeHoodDtoList) {
            if (fumeHoodDto.getLabId() != null) {
                Lab lab = labRepository.findById(fumeHoodDto.getLabId()).orElseGet(Lab::new);
                ValidationUtil.isNull( lab.getId(),"Lab","id",fumeHoodDto.getLabId());
                fumeHoodDto.setLabName(lab.getName());
            }
        }
        return fumeHoodDtoList;
    }

    @Override
    @Transactional
    public FumeHoodDto findById(Integer id) {
        FumeHood fumeHood = fumeHoodRepository.findById(id).orElseGet(FumeHood::new);
        ValidationUtil.isNull(fumeHood.getId(),"FumeHood","id",id);
        return fumeHoodMapper.toDto(fumeHood);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FumeHoodDto create(FumeHood resources) {
        return fumeHoodMapper.toDto(fumeHoodRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(FumeHood resources) {
        FumeHood fumeHood = fumeHoodRepository.findById(resources.getId()).orElseGet(FumeHood::new);
        ValidationUtil.isNull( fumeHood.getId(),"FumeHood","id",resources.getId());
        fumeHood.copy(resources);
        fumeHoodRepository.save(fumeHood);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            fumeHoodRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<FumeHoodDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (FumeHoodDto fumeHood : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("名称", fumeHood.getName());
            map.put("通风柜ip", fumeHood.getIp());
            map.put("实验室", fumeHood.getLabName());
            map.put("排风量", fumeHood.getExhaustAirRate());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Scheduled(cron = "0 0 * * * ?")
    @Override
    public void queryDataFromPLC() {
        List<FumeHood> fumeHoodList = fumeHoodRepository.findAll();
        if (fumeHoodList.isEmpty()) {
            return;
        }
        String ip;
        String address;
        byte byteData;
        int intData;
        for (FumeHood fumeHood : fumeHoodList) {
//            FumeHoodLog fumeHoodLog = new FumeHoodLog();
            if (fumeHood.getIp() == null || fumeHood.getAddress() == null) {
                continue;
            }
            ip = fumeHood.getIp();
            address = fumeHood.getAddress();
            SiemensS7Net siemensTcpNet = new SiemensS7Net(SiemensPLCS.S200, ip);
            OperateResult connect = siemensTcpNet.ConnectServer( );
            if (!connect.IsSuccess)
            {
                siemensTcpNet.ConnectClose();
                continue;
            }
            byteData = siemensTcpNet.ReadByte(address).Content;
            intData = byteData & 1;
            fumeHood.setIsOpen(intData);

            siemensTcpNet.ConnectClose();

            fumeHoodRepository.save(fumeHood);

//            fumeHoodLog.setFumeHoodId(fumeHood.getId());
//            fumeHoodLog.setIp(fumeHoodLog.getIp());
//            fumeHoodLog.setStatus(fumeHoodLog.getStatus());
        }
    }

    @Override
    public void openFumeHood(int id) {
        FumeHood fumeHood = fumeHoodRepository.findById(id).orElseGet(FumeHood::new);
        ValidationUtil.isNull(fumeHood.getId(),"FumeHood","id",id);
        if (fumeHood.getIp() == null) {
            return;
        }
        String ip = fumeHood.getIp();
        SiemensS7Net siemensTcpNet = new SiemensS7Net(SiemensPLCS.S200, ip);
        OperateResult connect = siemensTcpNet.ConnectServer( );
        if (!connect.IsSuccess)
        {
            siemensTcpNet.ConnectClose();
            return;
        }

        if (fumeHood.getOpenAddress() != null && fumeHood.getCloseAddress() != null) {
            siemensTcpNet.Write(fumeHood.getOpenAddress(), Convert.toBool(1));
            siemensTcpNet.Write(fumeHood.getCloseAddress(), Convert.toBool(0));
        }

        siemensTcpNet.ConnectClose();

        fumeHood.setIsOpen(1);
        fumeHoodRepository.save(fumeHood);
    }

    @Override
    public void closeFumeHood(int id) {
        FumeHood fumeHood = fumeHoodRepository.findById(id).orElseGet(FumeHood::new);
        ValidationUtil.isNull(fumeHood.getId(),"FumeHood","id",id);
        if (fumeHood.getIp() == null) {
            return;
        }
        String ip = fumeHood.getIp();
        SiemensS7Net siemensTcpNet = new SiemensS7Net(SiemensPLCS.S200, ip);
        OperateResult connect = siemensTcpNet.ConnectServer( );
        if (!connect.IsSuccess)
        {
            siemensTcpNet.ConnectClose();
            return;
        }

        if (fumeHood.getOpenAddress() != null && fumeHood.getCloseAddress() != null) {
            siemensTcpNet.Write(fumeHood.getOpenAddress(), Convert.toBool(0));
            siemensTcpNet.Write(fumeHood.getCloseAddress(), Convert.toBool(1));
        }

        siemensTcpNet.ConnectClose();

        fumeHood.setIsOpen(0);
        fumeHoodRepository.save(fumeHood);
    }
}
